package compilador.gerador;

import compilador.semantico.Atributo;
import compilador.semantico.TabelaSemantica;

public class GeradorDeCodigoColecao {

	private final static String FOR_ALL_TEMPLATE = "\tboolean NOMEINV() {\n\t\tboolean ok = true;\n\t\tfor(T V: COLEC) {\n\t\t\tok &= EXPR;\n\t\t}\n\t\treturn ok;\n\t}\n";
	private final static String EXISTS_TEMPLATE = "\tboolean NOMEINV() {\n\t\tfor(T V: COLEC) {\n\t\t\tif (EXPR) return true;\n\t\t}\n\t\treturn false;\n\t}\n";
	private final static String SELECT_TEMPLATE = "\tT[] NOMEINV() {\n\t\tjava.util.ArrayList<T> result = new java.util.ArrayList<T>();\n\t\tfor(T V: COLEC) {\n\t\t\tif (EXPR) result.add(V);\n\t\t}\n\t\treturn result.toArray(new T[result.size()]);\n\t}\n";

	public static final String NOMEINV = "NOMEINV";
	public static final String VARIAVEL = "V";
	public static final String TIPO = "T";
	public static final String LISTA = "COLEC";
	public static final String EXPR = "EXPR";

	public enum OperacaoColecao {
		FORALL, SELECT, EXISTS;
	}

	private static final GeradorDeCodigoColecao instance = new GeradorDeCodigoColecao();

	public static GeradorDeCodigoColecao getInstance() {
		return instance;
	}

	private String colecao;
	private String declarador;
	private String expr;

	private GeradorDeCodigoColecao() {

	}

	public void reset() {
		colecao = null;
		declarador = null;
		expr = null;
	}

	public void salvaColecao(String colecao) {
		this.colecao = colecao;
	}

	public void salvaDeclarador(String a) {
		this.declarador = a;
	}

	public void salvaExpressao(String expr) {
		this.expr = expr;
	}

	public String geraCodigo(String nomeInvariante, OperacaoColecao oper) {
		Atributo decl = TabelaSemantica.getInstance().getTemp(declarador);
		// se decl == null indica que houve um erro semantico
		// contudo o erro semantico ja foi notificado pelo analisador semantico
		if (decl != null) {
			String tipoDecl = decl.getTipo();
			String template = null;
			switch (oper) {
			case EXISTS:
				template = EXISTS_TEMPLATE;
				break;
			case FORALL:
				template = FOR_ALL_TEMPLATE;
				break;
			case SELECT:
				template = SELECT_TEMPLATE;
			}
			return geraCodigo(template, nomeInvariante, declarador, tipoDecl, colecao, expr);
		} 
		return "";
	}

	private String geraCodigo(String template, String nomeInv, String declarador, String tipoDecl, String colecao, String expr) {
		String result = template.replaceAll(NOMEINV, nomeInv);
		result = result.replaceAll(TIPO, tipoDecl);
		result = result.replaceAll(VARIAVEL, declarador);
		result = result.replaceAll(LISTA, colecao);
		result = result.replaceAll(EXPR, expr);
		return result;
	}

}
